package com.paw.portal.service.impl;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.paw.common.domain.Result;
import com.paw.portal.entity.SysMenu;
import com.paw.portal.entity.SysRoleMenu;
import com.paw.portal.request.dto.SysMenuRequestDto;
import com.paw.portal.response.dto.SysMenuResponseDto;
import com.paw.portal.service.IAntdMenuService;
import com.paw.portal.service.ISysMenuService;
import com.paw.portal.service.ISysRoleMenuService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * @author Rubble
 * @date 2021/8/24
 **/
@Service
public class AntdMenuServiceImpl implements IAntdMenuService {

  @Autowired
  private ISysMenuService sysMenuService;

  @Autowired
  private ISysRoleMenuService roleMenuService;


  @Override
  public Result<List<SysMenuResponseDto>> getMenuTreeList (SysMenuRequestDto requestDto) {
    SysMenu condition = new SysMenu();
    BeanUtils.copyProperties(requestDto,condition);
    LambdaQueryWrapper<SysMenu> queryWrapper = Wrappers.<SysMenu>lambdaQuery(condition)
        .ge(requestDto.getCreateTimeStart()!=null,SysMenu::getCreateTime,requestDto.getCreateTimeStart())
        .lt(requestDto.getCreateTimeEnd()!=null,SysMenu::getCreateTime,requestDto.getCreateTimeEnd());
    // 所有菜单
    List<SysMenu> allMenuList = sysMenuService.list();
    Map<Long, SysMenu> map = allMenuList.stream().collect(Collectors.toMap(SysMenu::getId, item -> item));
    // 查询菜单
    List<SysMenu> queryList = sysMenuService.list(queryWrapper);
    List<SysMenu> treeResultList = new ArrayList<>();
    if(queryList.size()==allMenuList.size()){
      treeResultList = allMenuList;
    }else {
      // 补充查找节点的父节点
      for (SysMenu menu : queryList) {
        fillMenuTreeParent(map,menu,treeResultList);
      }
    }
    // 构建tree
    List<SysMenuResponseDto> data = buildMenuTree(treeResultList,0L);
    Result<List<SysMenuResponseDto>> result = Result.success(data);
    return result;
  }

  @Override
  public Result<List<SysMenuResponseDto>> getMenuPageList (SysMenuRequestDto requestDto) {

    SysMenu condition = new SysMenu();
    BeanUtils.copyProperties(requestDto,condition);
    LambdaQueryWrapper<SysMenu> queryWrapper = Wrappers.<SysMenu>lambdaQuery(condition)
        .ge(requestDto.getCreateTimeStart()!=null,SysMenu::getCreateTime,requestDto.getCreateTimeStart())
        .lt(requestDto.getCreateTimeEnd()!=null,SysMenu::getCreateTime,requestDto.getCreateTimeEnd());
    Page<SysMenu> page = sysMenuService.page(new Page<>(requestDto.getCurrent(), requestDto.getPageSize()), queryWrapper);
    List<SysMenuResponseDto> data = new ArrayList<>();
    for (SysMenu record : page.getRecords()) {
      SysMenuResponseDto dto = new SysMenuResponseDto();
      BeanUtils.copyProperties(record,dto);
      data.add(dto);
    }
    Result<List<SysMenuResponseDto>> result = Result.page(data, page.getTotal());
    return result;
  }

  @Override
  @Transactional(rollbackFor = Exception.class)
  public Result<Boolean> delMenuWithChildren (Long id) {
    //递归查找所有子菜单
    List<SysMenu> menuList = new ArrayList<>();
    getChildrenMenu(id,menuList);
    List<Long> ids = menuList.stream().map(SysMenu::getId).collect(Collectors.toList());
    ids.add(id);

    boolean flag = sysMenuService.removeByIds(ids);
    // 删除
    if(flag){
      // 角色中关联的菜单
      roleMenuService.remove(Wrappers.<SysRoleMenu>lambdaQuery().in(SysRoleMenu::getMenuId,ids));
    }

    return Result.success(flag);
  }

  protected void getChildrenMenu(Long parentId,List<SysMenu> resultList){
    if(parentId==null){
      return;
    }
    List<SysMenu> children = sysMenuService.lambdaQuery().eq(SysMenu::getParentId, parentId).list();
    if(CollUtil.isNotEmpty(children)){
      resultList.addAll(children);
      for (SysMenu menu : children) {
        getChildrenMenu(menu.getId(),resultList);
      }
    }
  }


  private List<SysMenuResponseDto> buildMenuTree (List<SysMenu> sysMenuList,long parentId) {
    List<SysMenuResponseDto> list = new ArrayList<>();
    List<SysMenu> menus = sysMenuList.stream().filter(item -> item.getParentId() == parentId).collect(Collectors.toList());
    for (SysMenu menu : menus) {
      SysMenuResponseDto dto = new SysMenuResponseDto();
      BeanUtils.copyProperties(menu,dto);
      list.add(dto);
      List<SysMenuResponseDto> children = buildMenuTree(sysMenuList,menu.getId());
      if(CollUtil.isNotEmpty(children)){
        dto.setChildren(children);
      }
    }
    return list;
  }

  private void fillMenuTreeParent (Map<Long, SysMenu> map, SysMenu menu,List<SysMenu> resultList) {
    resultList.add(menu);
    if(menu.getParentId()!=0L && map.get(menu.getParentId())!=null){
      fillMenuTreeParent(map,map.get(menu.getParentId()),resultList);
    }
  }
}
